﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.IO;

namespace Project_02
{
    public partial class Form1 : Form
    {
        private sealed class RegexPattern {
            public static String username = "^[a-zA-Z0-9_]*$";
            public static String password = "^[^'*]$";
        }
        private Database database;
        private Boolean  state;
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            database = null;
            //Connect(true);
            //detailTabControl.SelectedIndex = detailTabControl.SelectedIndex = 2;
            SetState(false);
        }
        protected override CreateParams CreateParams {
            get {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x02000000;  // Turn on WS_EX_COMPOSITED
                return cp;
            }
        }
        private void UpdateUserList() {
            if (database == null) return;
            userListView.BeginUpdate();
            String username = (userListView.SelectedItems.Count > 0) ? userListView.SelectedItems[0].Text : "";
            userListView.Items.Clear();
            foreach (DataInfo user in database.User(filterTextBox.Text, browseCheckBox.Checked).List) {
                ListViewItem item = userListView.Items.Add(user.Name);
                if (user.Name == username) item.Selected = true;
            }
            if (userListView.Items.Count > 0 && userListView.SelectedIndices.Count == 0) userListView.Items[0].Selected = true;
            userListView.EndUpdate();
        }
        private void UpdateFriendList(List<DataInfo> list) {
            if (database == null) return;
            friendListView.BeginUpdate();
            friendListView.Items.Clear();
            foreach (DataInfo friend in list) {
                ListViewItem item = new ListViewItem(friend.Name);
                item.SubItems.Add(database.Relation.GetRelation(friend.ID));
                friendListView.Items.Add(item);
            }
            friendListView.EndUpdate();
        }
        private void UpdateStateList() {
            if (database == null) return;
            stateComboBox.BeginUpdate();
            stateComboBox.Items.Clear();
            foreach (DataInfo item in database.State.List) {
                stateComboBox.Items.Add(item.Name);
            }
            stateComboBox.SelectedIndex = 0;
            stateComboBox.EndUpdate();
        }
        private void UpdateGenderList() {
            if (database == null) return;
            genderComboBox.BeginUpdate();
            genderComboBox.Items.Clear();
            foreach (DataInfo item in database.Gender.List) {
                genderComboBox.Items.Add(item.Name);
            }
            genderComboBox.SelectedIndex = 0;
            genderComboBox.EndUpdate();
        }
        private void UpdateRankList() {
            if (database == null) return;
            rankComboBox.BeginUpdate();
            rankComboBox.Items.Clear();
            foreach (DataInfo item in database.Rank.List) {
                rankComboBox.Items.Add(item.Name);
            }
            rankComboBox.SelectedIndex = 0;
            rankComboBox.EndUpdate();
        }
        private void UpdateRelationList() {
            if (database == null) return;
            relationComboBox.BeginUpdate();
            relationComboBox.Items.Clear();
            foreach (DataInfo item in database.Relation.List) {
                relationComboBox.Items.Add(item.Name);
            }
            relationComboBox.SelectedIndex = 0;
            relationComboBox.EndUpdate();
        }
        private void UpdateFilterList() {
            if (database == null) return;
            filterComboBox.BeginUpdate();
            filterComboBox.Items.Clear();
            filterComboBox.Items.Add("");
            for (Char index = 'a'; index <= 'z'; ++index) {
                filterComboBox.Items.Add(index.ToString());
            }
            for (Byte index = 0; index <= 9; ++index) {
                filterComboBox.Items.Add(index.ToString());
            }
            filterComboBox.Items.Add("_");
            filterComboBox.SelectedItem = "";
            filterComboBox.EndUpdate();
        }
        private Boolean Connect(Boolean state) {
            if (state) {
                Connection form = new Connection();
                form.ShowDialog(this);
                state = (database = form.GetDatabase()) != null;
                //database = new Database("Botika-PC\\CRSSQLSERVER", "CyRius", "kornocska", 2);
                state = database != null;
                if (state) {
                    UpdateRankList();
                    UpdateStateList();
                    UpdateGenderList();
                    UpdateRelationList();
                    UpdateUserList();
                    UpdateFilterList();
                }
                SetState(state);
            } else if (MessageBox.Show("Are you sure you want to disconnect from the database?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.Yes) {
                database = null;
                SetState((state = false));
            } else
                state = true;
            return state;
        }
        private void SetState(Boolean state) {
            connectToolStripMenuItem.Text = (state) ? "Disconnect" : "Connect";
            linkLabel1.Visible = !state;
            panel1.Visible = state;
            documentationToolStripMenuItem.Visible = state;
            this.state = state;
        }
        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Connect(true);
        }
        private void connectToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Connect(!state);
        }
        private void consoleStripMenuItem1_Click(object sender, EventArgs e)
        {
            Hide();
            Console form = new Console();
            form.ShowDialog(this);
            Show();
        }
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            return;
            if (state) e.Cancel = Connect(false);
        }
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
        private void browseCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            UpdateUserList();
        }
        private void filterComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            filterTextBox.Text = filterComboBox.Text;
            UpdateUserList();
        }
        private void userListView_SelectedIndexChanged(object sender, EventArgs e)
        {
            RefreshData();
        }
        private void RefreshData() {
            if (database == null) return;
            if (userListView.SelectedItems.Count == 0) return;
            if (detailTabControl.SelectedTab.Text == "General") {
                GeneralInfo info = database.GetGeneral(userListView.SelectedItems[0].Text);
                UpdateStateList();
                usernameTextBox.Text = info.Username;
                passwordTextBox.Text = info.Password;
                shownameTextBox.Text = info.Name;
                stateComboBox.Text = info.State;
                statusTextBox.Text = info.Status;
            } else if (detailTabControl.SelectedTab.Text == "Private") {
                PrivateInfo info = database.GetPrivate(userListView.SelectedItems[0].Text);
                UpdateGenderList();
                UpdateRelationList();
                UpdateFriendList(info.Friend);
                genderComboBox.Text = info.Gender;
                birthdayDateTimePicker.Value = info.Birthday;
                questionTextBox.Text = info.Question;
                answerTextBox.Text = info.Answer;
            } else if (detailTabControl.SelectedTab.Text == "Custom") {
                CustomInfo info = database.GetCustom(userListView.SelectedItems[0].Text);
                UpdateRankList();
                rankComboBox.Text = info.Rank;
                banAdminTextBox.Text = info.Ban.Admin;
                banDateTimePicker.Value = info.Ban.Expire;
                banReasonTextBox.Text = info.Ban.Reason;
                silenceAdminTextBox.Text = info.Silence.Admin;
                silenceDateTimePicker.Checked = true;
                silenceDateTimePicker.Value = info.Silence.Expire;
                silenceReasonTextBox.Text = info.Silence.Reason;
                avatarPictureBox.Image = (info.Avatar.Image != null) ? info.Avatar.Image : avatarPictureBox.InitialImage;
            } else {
                feedbackLabel.Text = String.Format("Feedback count: {0:D}", database.GetFeedbackCount());
            }
            userLabel.Text = userListView.SelectedItems[0].Text;
            saveButton.Visible = (detailTabControl.SelectedTab.Text != "Reports and statistics");
        }
        private void detailTabControl_Selected(object sender, TabControlEventArgs e)
        {
            RefreshData();
        }
        private void avatarPictureBox_Click(object sender, EventArgs e)
        {
            if (database == null) return;
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.CheckFileExists = true;
            dialog.ReadOnlyChecked = true;
            dialog.ShowReadOnly = true;
            dialog.Title = "Choose an image!";
            dialog.FileName = "";
            dialog.DefaultExt = "txt";
            dialog.Filter = "Image files (*.bmp, *.png, *.jpg, *.gif)|*.bmp; *.png; *.jpg; *.gif";
            dialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
            if (dialog.ShowDialog(this) != DialogResult.OK) return;
            Avatar avatar = new Avatar(dialog.FileName);
            avatarPictureBox.Image = avatar.Image;
        }
        private void saveButton_Click(object sender, EventArgs e)
        {
            if (database == null) return;
            if (userListView.SelectedItems.Count == 0) return;
            try {
                if (detailTabControl.SelectedTab.Text == "General") {
                    database.SetGeneral(userListView.SelectedItems[0].Text, new GeneralInfo(usernameTextBox.Text, passwordTextBox.Text, shownameTextBox.Text, stateComboBox.Text, statusTextBox.Text));
                } else if (detailTabControl.SelectedTab.Text == "Private") {
                    List<DataInfo> list = new List<DataInfo>();
                    foreach (ListViewItem item in friendListView.Items) {
                        list.Add(new DataInfo(item.Text, database.Relation.GetID(item.SubItems[1].Text)));
                    }
                    database.SetPrivate(userListView.SelectedItems[0].Text, new PrivateInfo(genderComboBox.Text, birthdayDateTimePicker.Value, questionTextBox.Text, answerTextBox.Text, list));
                } else {
                    BanInfo banInfo = (!(banAdminTextBox.Text == "")) ? new BanInfo(banAdminTextBox.Text, banDateTimePicker.Value, banReasonTextBox.Text) : new BanInfo();
                    SilenceInfo silenceInfo = (!(silenceAdminTextBox.Text == "")) ? new SilenceInfo(silenceAdminTextBox.Text, silenceDateTimePicker.Value, silenceReasonTextBox.Text) : new SilenceInfo();
                    database.SetCustom(userListView.SelectedItems[0].Text, new CustomInfo(rankComboBox.Text, new Avatar(avatarPictureBox.Image), banInfo, silenceInfo));
                }
                UpdateUserList();
                RefreshData();
            } catch(Exception ex) {
                MessageBox.Show(ex.Message, "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
            }
        }
        private void filterTextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter) {
                e.SuppressKeyPress = true;
                if (filterTextBox.Text.Length == 0 && MessageBox.Show("The filter is empty!\nRequesting a large amount of usernames from the server may block/crash the application!\nAre you sure you want to proceed anyway?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != DialogResult.Yes) return;
                if (!Regex.Match(filterTextBox.Text, RegexPattern.username).Success) MessageBox.Show("The filter can contain only underscores (\"_\"), letters and numbers!", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                UpdateUserList();
            }
        }
        private void filterTextBox_TextChanged(object sender, EventArgs e)
        {
            if (filterTextBox.Text.Length == 1) filterComboBox.SelectedItem = filterTextBox.Text[0].ToString();
        }
        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form form = new About();
            form.ShowDialog(this);
        }
        private void reportButton_Click(object sender, EventArgs e)
        {
            if (database == null) return;
            database.GetReport(rankCheckBox.Checked, genderCheckBox.Checked, stateCheckBox.Checked, banCheckBox.Checked, silenceCheckBox.Checked);
        }
        private void feedbackButton_Click(object sender, EventArgs e)
        {
            if (database == null) return;
            database.GetFeedback();
        }
        private void addButton_Click(object sender, EventArgs e)
        {
            if (database == null) return;
            try {
                if (database.GetBlacklistAddress(ipTextBox.Text)) {
                    if (MessageBox.Show("This address is already blacklisted!\nDo you want to update it with the new reason?", "Warning!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
                        database.EditBlacklist(ipTextBox.Text, reasonTextBox.Text);
                } else
                    database.AddBlacklist(ipTextBox.Text, reasonTextBox.Text);
            } catch(Exception ex) {
                MessageBox.Show("This is not a valid IP address", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }
        private void removeButton_Click(object sender, EventArgs e)
        {
            if (database == null) return;
            database.RemoveBlacklist(ipTextBox.Text);
        }
        private void friendListView_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (database == null) return;
            if (friendListView.SelectedItems.Count == 0) return;
            friendTextBox.Text = friendListView.SelectedItems[0].Text;
            relationComboBox.Text = friendListView.SelectedItems[0].SubItems[1].Text;
        }
        private void friendAddButton_Click(object sender, EventArgs e)
        {
            if (database == null) return;
            String name = friendTextBox.Text;
            int index = getFriend(name);
            if (index >= 0)
                friendListView.Items[index].SubItems[1].Text = relationComboBox.Text;
            else {
                ListViewItem item = new ListViewItem(name);
                item.SubItems.Add(relationComboBox.Text);
                friendListView.Items.Add(item);
            }
        }
        private void friendRemoveButton_Click(object sender, EventArgs e)
        {
            if (database == null) return;
            String name = friendTextBox.Text;
            int index = getFriend(name);
            if (index >= 0) friendListView.Items.RemoveAt(index);
            else MessageBox.Show("The friend \"" + name + "\" does not exists!", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
        private int getFriend(String name) {
            foreach (ListViewItem item in friendListView.Items) {
                if (item.Text == name) return friendListView.Items.IndexOf(item);
            }
            return -1;
        }
        private void documentationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try {
                String file = "C:\\Users\\Botika\\Desktop\\Trash\\Egyetem\\ProiectIndividual\\AdminPanel_UserDoc.doc";
                System.Diagnostics.Process.Start(file);
            } catch(Exception ex) {
                MessageBox.Show("The user documentation cannot be found or opened!" + Environment.NewLine + ex.Message + "!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }
    }
}
